home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 25
/
Cream of the Crop 25.iso
/
bbs
/
doorinfo.zip
/
ZMSEND.C
< prev
Wrap
C/C++ Source or Header
|
1997-05-14
|
25KB
|
1,187 lines
/*
**************************************************************************
**
** Doors program to send files via zmodem
**
** Compile instructions for MSC 5.1 and 6.0
** Note - structs.h hsz.h and bbscfg.h are required.
** these files, and lmtca.obj, are available in doorinfo.zip
**
** cl /c /AL /Gs zmsend.c
** link /st:4096 zmsend lmtca fsubs;
**
**************************************************************************
*/
/*
#define DBG
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <time.h>
#include "hsz.h"
#include "structs.h"
#include "bbscfg.h"
#include "fossil.h"
#include "c:\mt\tcb.h"
#include "crctab.c"
#include "sendraw.h"
void sendzrqinit(void);
void sendzfile(char *name);
void waitforzack(void);
void waitforzrinit(void);
void sendzsinit(void);
void sendzfin(void);
void sendzeof(void);
void sendbindata(char *buf, int length, int frameend);
void zsda32(char *buf, int length, int frameend);
void zsendline(int c);
void sendzdata(void);
void sendbinhdr(char *buf, int count);
void sendhexhdr(char *buf, int count);
void bsend(char *str);
int endtask(void);
int sendblock(void);
void clear_queue(int q);
int calccrc(char *buf, int len);
int calccrc32(char *buf, int len);
int check_timer(time_t tim);
void getfilename(char *buf1, char *buf2);
int check_q(void);
int check_ring_buf(void);
#define MY_buf_size 12*1024
typedef struct acct_rec acctp[];
typedef struct user_rec userp[];
struct cfg_rec far *cfg; /* pointer to BBSCFG record */
acctp far *acct;
userp far *user; /* pointer to an array of user_rec
* structue\res */
time_t t;
char MY_buf[MY_buf_size];
FILE *logfp;
int sendbufsize;
int blocks_since_nak;
struct find_t fin;
#define NAK 21
#define CAN 24
int blocksize;
unsigned int rbufsiz; /* the receiver's buffer size */
char fname[80];
char hdrbuf[40];
char buffer[2100];
char buffer2[2100];
char secbuf[2100];
char namebuf[1000];
long filepos;
long filepos_save;
int escapeall = 0; /* normally we don;t escape all characters */
int crc32 = 0; /* use 16 or 32 bit crc */
int waitforack = 0; /* streaming/nonstreaming */
int recvmode; /* used to determine how much of header
* received */
int hdrincnt; /* must receive 13 bytes */
/* type, 8 bytes of flags, 4 bytes of crc, in ascii hex */
int cancount = 0;
struct msg1
{ /* used for text in/out */
int m1typ;
int m1num; /* line number */
char m1text[1000];
} *m1;
struct msg3
{ /* the initial message with line num and
* queue nums */
int m3typ; /* must be 7 */
int m3line;
int m3inq;
int m3outq;
void far *acctptr;
void far *userptr;
int maxline;
struct cfg_rec far *cfgptr; /* pointer to BBSCFG record */
} *m3;
char lbuf[128]; /* a little work buffer */
int who;
int inq, outq;
FILE *fp;
void main(int argc, char *argv[])
{
int j, k, n;
int alldone = 0;
logfp = fp = NULL;
setpri(7);
m1 = (struct msg1 *) buffer;
m3 = (struct msg3 *) buffer;
/*
** wait for the initialization event from FALKEN.
** it will be event type 7.
** If for some reason we get an event type 8, we must terminate.
*/
m3->m3typ = 0;
time(&t);
while (m3->m3typ != 7)
{
if (testmsg(1))
{
recvmsg(1, buffer, 1000);
if (m3->m3typ == 8)
{
endtask();
}
}
else if (check_timer(t) > 10)
{
endtask();
}
relinq();
}
acct = m3->acctptr;
user = m3->userptr;
cfg = m3->cfgptr;
/*
** get the input and output queue numbers we have been assigned,
** and which line this user is logged on to.
*/
inq = m3->m3inq;
outq = m3->m3outq;
who = m3->m3line;
/*
** Now the main loop -
*/
if (argc > 1)
{
strcpy(namebuf, argv[1]);
j = 2;
while (j < argc)
{
strcat(namebuf, ",");
strcat(namebuf, argv[j++]);
}
clear_queue(inq);
}
else /* need an event with file names in it */
{
n = 0; /* wait for the text message with filenames */
time(&t);
for (;;)
{
if (testmsg(inq))
{
recvmsg(inq, buffer, 1000);
if (m1->m1typ == 8)
{
endtask();
}
else if (m1->m1typ == 1)
{
if (strncmp(m1->m1text, "filename=", 9) == 0)
{
strcpy(namebuf, m1->m1text + 9);
break;
}
}
}
if (check_timer(t) > 30)
{
endtask();
}
relinq();
}
}
for (j = 0; namebuf[j]; j++)
{
if (namebuf[j] == ' ')
namebuf[j] = ',';
}
/*
** If this is a mux line, we have to wait for ack after every block,
** to prevent overrunning the mux's buffers
*/
if (strnicmp(cfg->modem_init_str[who], "mux", 3) == 0)
{
bsend("Zmodem cannot be run on a multiplexed line.\r\n");
bsend("Please restart your download with Xmodem or Ymodem.\r\n");
delay(1);
exit(0);
}
m1->m1typ = 8;
send_md_msg(outq, buffer, 2);
delay(1);
bsend("Zmodem Batch file download activated.\r\n");
bsend("Start your Zmodem transfer now....\r\n");
/*
** Now we have to establish the zmodem dialogue. We are the sender,
** so we have to send ZRQINIT packets to the receiver telling him we
** are ready to go!
*/
sendbufsize = 1024; /* start at 1K bytes */
blocks_since_nak = 0;
n = 0; /* ZRINIT not received yet */
time(&t);
j = 0; /* how many ZRQINIT packets have we sent ? */
recvmode = 0; /* no pad received */
hdrincnt = 0;
sendzrqinit(); /* send the first zrqinit packet */
while (n == 0)
{
if (k = check_q()) /* see if we got a header in */
{
switch (k)
{
case 1: /* packet received */
if (hdrbuf[0] == ZRINIT)
{
n = 1; /* what we were waiting for! */
if ((hdrbuf[1 + ZF0] & CANFDX) &&
(hdrbuf[1 + ZF0] & CANOVIO))
waitforack = 0;
else
waitforack = 1;
if (hdrbuf[1 + ZF0] & ESCCTL)
escapeall = 1;
else
escapeall = 0;
if (hdrbuf[1 + ZF0] & CANFC32)
crc32 = 1;
else
crc32 = 0;
rbufsiz = (hdrbuf[1 + ZP1] << 8) + hdrbuf[1 + ZP0];
/*
** If receiver has set the buffer size variable to non-zero, it
** indicates the largest buffer (window) he can have outstanding.
** If 0, we can send at will, otherwise, we will only send one
** block at a time, and wait for the ack.
** THIS IS A KLUGE!
** At some point, we should keep track of outstanding (un-acked)
** bytes, and turn transmitter off then, rather than just blindly
** sending one block and waiting for ack.
*/
if (rbufsiz != 0)
waitforack = 1;
else
waitforack = 0;
}
break;
case 4: /* no data waiting, so outbuf counter ret's */
break;
case 0: /* got data in, but not complete header */
time(&t); /* reset the timeout */
break;
}
}
if (!n && (check_timer(t) > 1))
{
if (++j > 60)
{
endtask(); /* waited too long for zrinit */
}
sendzrqinit();
time(&t);
}
}
/*
** We got the ZRINIT packet, so now we send a ZSINIT packet with
** various options set for every file we wish to send.
*/
sendzsinit();
waitforzack();
while (alldone == 0)
{
getfilename(namebuf, fname);
/*
** when all file names have been exhausted, get out.
*/
if (!strlen(fname))
{
sendzfin();
alldone = 1;
}
else
{
sendzfile(fname);
waitforzrinit();
}
} /* end outer forever loop */
bsend("\rTransfer Successful.\r\r");
delay(1);
endtask();
}
void sendzrqinit()
{
int j;
lbuf[0] = ZRQINIT; /* type */
for (j = 1; j < 5; j++)
lbuf[j] = 0; /* set flags to 0 */
sendhexhdr(lbuf, 5);
}
void sendzfile(name)
char *name;
{
int j, k, n;
int datacount;
int lastframe;
char *ip;
char outbuf[80];
char obuf[16];
ip = (char *) &filepos;
obuf[0] = ZFILE;
filepos_save = 0L;
filepos = 0L; /* initialize filepos to beginning of file */
/*
** Flags - ZF1 set for binary transfer, optional file recovery of
** aborted transfers.
*/
obuf[1 + ZF0] = ZCBIN;
obuf[1 + ZF1] = 0;
obuf[1 + ZF2] = 0;
obuf[1 + ZF3] = 0;
sendbinhdr(obuf, 5); /* send the header */
sprintf(outbuf, "%s %ld", name, fin.size); /* fin loaded in
* getfilename() */
j = strlen(outbuf);
for (k = 0; outbuf[k] != ' '; k++);
outbuf[k] = '\0'; /* insert a null between name and size */
k = 0;
for (n = 0; n < j; n++)
secbuf[k++] = outbuf[n];/* move name, size */
secbuf[k++] = '\0'; /* null to terminate the file len */
sendbindata(secbuf, k, ZCRCW);
datacount = k;
recvmode = 0;
hdrincnt = 0;
waitforzack();
sendzdata();
lastframe = ZCRCG;
/*
** Now we loop, checking how many bytes are free in the line's
** transmit buffer, checking the input queue, and sending binary
** subpackets whenever we can.
*/
for (;;)
{
if (k = check_q()) /* see if we got a header in */
{
switch (k)
{
case 1: /* packet received */
switch (hdrbuf[0])
{
case ZRPOS:
case ZACK:
ip[0] = hdrbuf[1 + ZP0];
ip[1] = hdrbuf[1 + ZP1];
ip[2] = hdrbuf[1 + ZP2];
ip[3] = hdrbuf[1 + ZP3];
if ((lastframe != ZCRCW) && (lastframe != ZCRCE))
sendbindata(outbuf, 0, ZCRCE); /* empty CRCE packet */
sendzdata(); /* send a data header */
goto sendnext;
break;
case ZSKIP: /* receiver says skip this file */
return; /* return to main routine */
break;
case ZABORT: /* receiver aborts batch file xfer */
lbuf[0] = ZFIN;
lbuf[1] = lbuf[2] = lbuf[3] = lbuf[4] = 0; /* flags to 0 */
sendhexhdr(lbuf, 5);
bsend("\r\n\nZMODEM transfer aborted by receiver !\r\n\n");
delay(2);
endtask();
case ZNAK: /* last header was garbled. resend
* it */
blocks_since_nak = 0;
if (sendbufsize > 512)
sendbufsize = 512;
sendbinhdr(obuf, 5);
sendbindata(secbuf, datacount, ZCRCW);
break;
}
break;
/*
** A little tricky here.
** Any time the the output buffer is empty, we will
** send the next data block. If we are to wait for an acknowledgement,
** then we wait for the ack, then send the next header right away.
** The header is less than 100 bytes, so we come through again, and see
** that the outbuf count < 100, and we go ahead and send the data to go
** with that header.
**
*/
case 4: /* outbuf counter received. */
sendnext:
/*
** If we got a zrpos or a zrnak, we have reset our filepos pointer,
** so, if the old filepos and the new one are different, there was
** an error on a block. If so, knock the block size down.
** When we get 4 good blocks through, increment block size.
*/
if (filepos == filepos_save) /* good block ? */
{
if (blocks_since_nak < 2)
blocks_since_nak++;
else
{
blocks_since_nak = 0; /* start counting again */
if (sendbufsize < 1024)
sendbufsize = 1024;
}
}
else /* error - resending a block */
{
blocks_since_nak = 0;
if (sendbufsize > 512)
sendbufsize = 512;
}
lastframe = j = sendblock(); /* send the next block */
switch (j) /* sendblock returns type of block sent */
{
case ZCRCW:
waitforzack(); /* must wait for ack */
sendzdata(); /* need to send new packet
* hdr */
break;
case ZCRCE:
sendzeof();
if (fp != NULL)
{
fclose(fp);
fp = NULL;
}
return; /* now wait for new zrinit */
break;
}
break;
} /* end outer switch */
} /* end if check_q */
} /* end for(;;) */
}
/*
** Utility routines follow
**
** These routines call Multidos interface routines which are available
** with the FALKEN Doors development kit.
**
** See the file MDOS.TXT for a description of the interface routines.
*/
/*
** wait for a hex header that acknowledges a block
** all ZACK frames contain a file offset. set it up.
*/
void waitforzack()
{
int k, n;
char *ip;
ip = (char *) filepos;
recvmode = 0;
hdrincnt = 0;
n = 0;
while (n == 0)
{
if (k = check_q()) /* see if we got a header in */
{
switch (k)
{
case 1: /* packet received */
switch (hdrbuf[0])
{
case ZRINIT:
sendzsinit();
break;
case ZACK:
case ZRPOS:
n = 1; /* what we were waiting for! */
ip[0] = hdrbuf[1 + ZP0]; /* get new file position */
ip[1] = hdrbuf[1 + ZP1];
ip[2] = hdrbuf[1 + ZP2];
ip[3] = hdrbuf[1 + ZP3];
break;
case ZNAK:
memcpy(buffer, buffer2, 1100);
sendraw(who, buffer + 4, m1->m1num);
break;
}
break;
case 4: /* no data - btuoba returned */
break;
}
}
}
}
void waitforzrinit()
{
int k, n;
recvmode = 0;
hdrincnt = 0;
n = 0;
while (n == 0)
{
if (k = check_q()) /* see if we got a header in */
{
switch (k)
{
case 1: /* packet received */
switch (hdrbuf[0])
{
case ZRPOS:
case ZACK:
case ZNAK:
sendzeof();
break;
case ZRINIT:
n = 1;
break;
case ZABORT:
delay(1);
endtask();
break;
}
break;
case 4:
break;
}
}
}
}
void sendzsinit()
{
int j;
lbuf[0] = ZSINIT; /* type */
for (j = 1; j < 5; j++)
lbuf[j] = 0; /* set flags to 0 */
sendbinhdr(lbuf, 5);
sendbindata(lbuf, 0, ZCRCW);/* send an empty data packet - no break */
}
void sendzfin()
{
int j;
lbuf[0] = ZFIN; /* type */
for (j = 1; j < 5; j++)
lbuf[j] = 0; /* set flags to 0 */
sendhexhdr(lbuf, 5);
}
void sendzeof()
{
char *cp;
cp = (char *) &filepos;
lbuf[0] = ZEOF; /* type */
lbuf[1 + ZP0] = cp[0]; /* set file position in the flags/position
* bytes */
lbuf[1 + ZP1] = cp[1];
lbuf[1 + ZP2] = cp[2];
lbuf[1 + ZP3] = cp[3];
sendhexhdr(lbuf, 5);
(*acct)[who].dloads++;
(*acct)[who].download_k += filepos / 1024L;
}
char *outbuf;
int outbufcnt;
char lastsent;
#define xsendline(c) outbuf[outbufcnt++]=0xff&(c)
void sendbindata(buf, length, frameend)
char *buf;
int length;
int frameend;
{
unsigned short crc;
int k;
outbuf = m1->m1text;
outbufcnt = 0;
lastsent = 0;
if (crc32)
zsda32(buf, length, frameend);
else
{
crc = 0;
for (k = 0; k < length; k++)
{
zsendline(buf[k]);
crc = updcrc((0377 & buf[k]), crc);
}
crc = updcrc(frameend, crc);
xsendline(ZDLE);
xsendline(frameend);
crc = updcrc(0, updcrc(0, crc));
zsendline((crc >> 8) & 0xff);
zsendline(crc & 0xff);
}
if (frameend == ZCRCW)
{
xsendline(17);
}
sendraw(who, outbuf, outbufcnt);
}
void zsda32(buf, length, frameend)
char *buf;
int length;
int frameend;
{
int c;
unsigned long crc;
crc = 0xFFFFFFFFL;
for (; --length >= 0; ++buf)
{
c = *buf & 0377;
if (c & 0140)
xsendline(lastsent = c);
else
zsendline(c);
crc = UPDC32(c, crc);
}
xsendline(ZDLE);
xsendline(frameend);
crc = UPDC32(frameend, crc);
crc = ~crc;
for (length = 4; --length >= 0;)
{
zsendline((int) crc);
crc >>= 8;
}
}
/*
* Send character c with ZMODEM escape sequence encoding.
* Escape XON, XOFF. Escape CR following @ (Telenet net escape)
*/
void zsendline(c)
{
/* Quick check for non control characters */
if (c & 0140)
xsendline(lastsent = c);
else
{
switch (c &= 0377)
{
case ZDLE:
xsendline(ZDLE);
xsendline(lastsent = (c ^= 0100));
break;
case 015:
case 0215:
if ((!escapeall) && (lastsent & 0177) != '@')
goto sendit;
/* **** FALL THRU TO **** */
case 020:
case 021:
case 023:
case 0220:
case 0221:
case 0223:
xsendline(ZDLE);
c ^= 0100;
sendit:
xsendline(lastsent = c);
break;
default:
if (escapeall && !(c & 0140))
{
xsendline(ZDLE);
c ^= 0100;
}
xsendline(lastsent = c);
}
}
}
void sendzdata()
{
char *cp;
cp = (char *) &filepos;
lbuf[0] = ZDATA; /* type */
lbuf[1 + ZP0] = cp[0]; /* set file position in the flags/position
* bytes */
lbuf[1 + ZP1] = cp[1];
lbuf[1 + ZP2] = cp[2];
lbuf[1 + ZP3] = cp[3];
sendbinhdr(lbuf, 5);
}
void sendbinhdr(buf, count)
char *buf;
int count;
{
int j, k;
char *outbuf;
j = k = 0;
/* calccrc returns new buffer length */
if (crc32)
count = calccrc32(buf, count);
else
count = calccrc(buf, count);
outbuf = m1->m1text;
j = 0;
outbuf[j++] = ZPAD;
outbuf[j++] = ZDLE;
if (crc32)
outbuf[j++] = 'C';
else
outbuf[j++] = 'A'; /* send binary header! */
for (k = 0; k < count; k++)
{
if (buf[k] == ZDLE)
{
outbuf[j++] = ZDLE;
outbuf[j++] = ZDLEE;
}
else if (escapeall)
{
if ((buf[k] & 0xc0) == 0) /* if bits 5 and 6 reset */
{
outbuf[j++] = ZDLE;
outbuf[j++] = buf[k] | 0x40;
}
else if (buf[k] == 0x7f)
{
outbuf[j++] = ZDLE;
outbuf[j++] = 'l';
}
else if (buf[k] == 0xff)
{
outbuf[j++] = ZDLE;
outbuf[j++] = 'm';
}
else
outbuf[j++] = buf[k];
}
else /* only escape the xon xoff stuff */
{
if (((buf[k] & 0x7f) >= 16) && ((buf[k] & 0x7f) < 20))
{
outbuf[j++] = ZDLE;
outbuf[j++] = buf[k] | 0x40;
}
else
outbuf[j++] = buf[k];
}
} /* end for */
memcpy(buffer2, buffer, j + 4); /* save a copy of the last
* transmission */
sendraw(who, outbuf, j);
}
void sendhexhdr(buf, count)
char *buf;
int count;
{
int j, k;
char *outbuf;
char w[14];
j = k = 0;
count = calccrc(buf, count);/* calccrc returns new buffer length */
outbuf = m1->m1text;
j = 0;
outbuf[j++] = ZPAD;
outbuf[j++] = ZPAD;
outbuf[j++] = ZDLE;
outbuf[j++] = 'B'; /* send hex header! */
for (k = 0; k < count; k++)
{
sprintf(w, "%02x", (int) 0xff & buf[k]);
outbuf[j++] = w[0];
outbuf[j++] = w[1];
}
outbuf[j++] = '\r';
outbuf[j++] = '\n';
outbuf[j++] = 17; /* x-on */
memcpy(buffer2, buffer, j + 4); /* save a copy of the last
* transmission */
sendraw(who, outbuf, j);
}
/*
** Send a null terminated string to FALKEN, to be transmitted to
** a particular line;
*/
void bsend(str)
char *str;
{
sendraw(who, str, strlen(str));
}
/*
** This program gracefully exits by
** sending the 'task has terminated' message to FALKEN,
** then terminating.
*/
int endtask()
{
/*
** Put line parameters back the way they were
*/
if (logfp != NULL)
fclose(logfp);
if (fp != NULL)
fclose(fp);
delay(1);
exit(0);
}
int sendblock()
{
int j;
/*
** if the file offset has changed, via a zrpos or zack, then do an
** fseek to get to the right file position
*/
if (filepos_save != filepos)
{
fseek(fp, filepos, SEEK_SET);
}
blocksize = fread(secbuf, 1, sendbufsize, fp);
filepos += blocksize;
filepos_save = filepos; /* remember the old offset */
if (feof(fp)) /* end of file reached ? */
{
j = ZCRCE;
}
else
{
if (!waitforack)
j = ZCRCG; /* we want to stream output! */
else
j = ZCRCW; /* guess not */
j = ZCRCW;
}
sendbindata(secbuf, blocksize, j);
return j; /* return block type sent */
}
void clear_queue(q)
int q;
{
while (testmsg(q) > 0)
recvmsg(q, buffer, 1024);
f_flushin(who);
f_flushout(who);
}
calccrc(buf, len)
char *buf;
int len;
{
unsigned int c;
int j;
c = 0;
for (j = 0; j < len; j++)
c = updcrc((255 & buf[j]), c);
c = updcrc(0, c);
c = updcrc(0, c);
buf[j++] = (c >> 8) & 0xff;
buf[j++] = c & 0xff;
return j; /* returns length of buffer, counting crc */
}
calccrc32(buf, len)
char *buf;
int len;
{
unsigned long int c;
int j, k;
c = 0xffffffffL;
for (j = 0; j < len; j++)
{
k = 0xff & buf[j];
c = UPDC32(k, c);
}
c = ~c;
for (k = 0; k < 4; k++)
{
buf[j++] = (char) c;
c >>= 8;
}
return j; /* returns length of buffer, counting crc */
}
check_timer(time_t tim)
{
time_t curt;
time(&curt);
return ((int) curt - tim);
}
/*
** We will get the next file name from buf1, and place it into buf2.
** Notice that when we copy it into buf2, we strip off the directory
** information, so that all we keep in buf2 is the file name itself.
** We build a full path and file name in buf3 to use when opening
** the file.
*/
void getfilename(buf1, buf2)
char *buf1, *buf2;
{
int j, k, n, m;
gnam:
n = m = k = 0;
while (buf1[n] == ',')
n++; /* skip the used spaces */
while (buf1[n] != ',')
{
if (buf1[n] == '\0')
break;
if (buf1[n] == '\\' || buf1[n] == ':')
m = 0; /* no path info in this one */
else
buf2[m++] = buf1[n];
lbuf[k++] = buf1[n];
buf1[n++] = ','; /* set to comma so we skip it next time */
}
buf2[m] = '\0';
lbuf[k] = '\0';
if (m == 0 || k == 0)
return; /* no file name found! */
j = _dos_findfirst(lbuf, _A_NORMAL, &fin); /* is it a real file ? */
if (j)
goto gnam;
fp = fopen(lbuf, "rb");
if (fp == NULL)
goto gnam;
setvbuf(fp, MY_buf, _IOFBF, MY_buf_size);
}
check_q()
{
int j, k, m, n;
n = 0;
if ((n = check_ring_buf()) == 0) /* return # chars read */
{
if (testmsg(inq))
{
recvmsg(inq, buffer, 1000);
n = 1;
}
else
{
n = f_status(who);
if (n & 0x6000) /* output buffer empty ? */
return 4;
else
return 5;
}
}
switch (m1->m1typ)
{
case 8: /* terminate command */
endtask();
case 2: /* binary data in */
m1->m1text[m1->m1num] = '\0';
for (j = 0; j < m1->m1num; j++)
{
if (m1->m1text[j] == ZDLE)
{
if (++cancount >= 4)
endtask();
}
else
cancount = 0;
switch (recvmode)
{
case 0: /* waiting for zpad */
if (m1->m1text[j] == ZPAD)
{
recvmode = 1; /* got header, looking for
* ZDLE */
/* not gonna get zdle, get B */
}
/*
** Got zpad. If next byte not zpad or zdle, start looking for zpad again
** if zpad, continue looking for zdle.
** if zdle, look for header type
*/
break;
case 1: /* got zpad, looking for zdle */
if (m1->m1text[j] == ZPAD)
break; /* ignore */
else if (m1->m1text[j] == ZDLE)
recvmode = 2;
/*
** we must get the 'B' next if this is a ZDLE
** we may get the 'B' without a ZDLE. This is OK, we just start
** accumulating the header
*/
else if (m1->m1text[j] == 'B')
{
recvmode = 3;
hdrincnt = 0;
}
else
recvmode = 0; /* not one of these - error */
break;
case 2: /* got zdle - look for header type. */
if (m1->m1text[j] != 'B')
recvmode = 0; /* must be B */
else
{
recvmode = 3; /* start assembling data */
hdrincnt = 0;
}
break;
/*
** we are now receiving the data packet from the receiver.
** It MUST be a hex header, and will be exactly 14 bytes long.
** Type(2) plus 4 flags(8) plus 2 CRC bytes(4) = 14
** hex encoding, of course
** if we get a bad character in, go back to waiting for ZPAD
*/
case 3: /* now assemble the packet */
k = m1->m1text[j];
if (((k >= '0') && (k <= '9')) || ((k >= 'a') && (k <= 'f')))
{
hdrbuf[hdrincnt++] = m1->m1text[j];
if (hdrincnt >= 14)
{
for (j = k = 0; j < 7; j++)
{
n = hdrbuf[k++];
if (n <= '9')
n -= '0';
else
n = (n - 'a') + 10;
m = hdrbuf[k++];
if (m <= '9')
m -= '0';
else
m = (m - 'a') + 10;
hdrbuf[j] = n * 16 + m;
}
recvmode = 0;
return 1; /* show we got a header */
}
}
else
recvmode = 0;
break;
} /* end switch */
} /* end for */
} /* end switch */
/*
** If we get here, we want to return 0, showing we didn;t get anything
*/
return 0;
}
check_ring_buf()
{
int n;
n = f_status(who);
if ((n & 0x100) == 0) /* anything in input buffer ? */
return 0;
n = f_recv(who, m1->m1text, 1024);
m1->m1text[n] = '\0';
m1->m1typ = 2;
m1->m1num = n;
return 2;
}